package org.itzixi.zk;

import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.CuratorCache;
import org.apache.curator.framework.recipes.cache.CuratorCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
//import org.itzixi.base.BaseInfoProperties;
import org.itzixi.pojo.netty.NettyServerNode;
import org.itzixi.utils.JsonUtils;
import org.itzixi.utils.RedisOperator;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Objects;

@Slf4j
@Configuration
@Data
@ConfigurationProperties(prefix = "zookeeper.curator")
public class CuratorConfig {

    @Resource
    private RedisOperator redisOperator;

    @Resource
    private RabbitAdmin rabbitAdmin;

    /**
     * zookeeper:
     *   curator:
     *     #    host: 192.168.1.121:2181,192.168.1.122:2181,192.168.1.123:2181
     *     host: 127.0.0.1:2181
     *     connectionTimeoutMs: 30000
     *     sessionTimeoutMs: 3000
     *     sleepMsBetweenRetry: 2000
     *     maxRetries: 3
     *     namespace: itzixi-im
     */
    private String host;
    private Integer connectionTimeoutMs;
    private Integer sessionTimeoutMs;
    private Integer sleepMsBetweenRetry;
    private Integer maxRetries;
    private String namespace;

    private static final String PATH = "/server-list";

    @Bean(value = "curatorClient")
    public CuratorFramework curatorClient(){
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(sleepMsBetweenRetry, maxRetries);
        //        client.start();
        CuratorFramework client =  CuratorFrameworkFactory.builder()
                .retryPolicy(retryPolicy)
                .connectionTimeoutMs(connectionTimeoutMs)
                .sessionTimeoutMs(sessionTimeoutMs)
                .namespace(namespace)
                .connectString(host)
                .build();
        client.start();
        log.info("CuratorFramework客户端已经成功启动！！！！");
        // 注册监听事件
        addWatcher(PATH, client);
        return client;
    }

    /**
     * 注册节点的事件监听
     * @param path 监听的节点
     * @param client 客户端
     */
    public void addWatcher(String path, CuratorFramework client){
        CuratorCache curatorCache = CuratorCache.build(client, path);
        curatorCache.listenable().addListener((type, oldData, data) -> {
            String eventName = type.name();


            log.info("节点更新后的数据、状态:{}", data);
            switch (eventName) {
                case "NODE_CREATED" -> log.info("子节点创建事件");
                case "NODE_CHANGED" -> log.info("子节点更新事件");
                case "NODE_DELETED" -> {
                    log.info("子节点删除事件");
                    String oldDataJson = new String(oldData.getData());
                    NettyServerNode oldNode = JsonUtils.jsonToPojo(oldDataJson, NettyServerNode.class);
                    log.info("old path:{}", oldData.getPath());
                    log.info("old node:{}", oldNode);
                    if (Objects.nonNull(oldNode)) {
                        String oldPort = oldNode.getPort() + "";
                        String portKey = "netty_port";
                        redisOperator.hdel(portKey, oldPort);

                        // 删除mq中残留的节点
                        String queueName = "netty_queue_"  + oldPort;
                        rabbitAdmin.deleteQueue(queueName);
                    }
                }
            }


            // System.out.println("new path:" + data.getPath() + ",
            // new value:" + data.getData());

            //NODE_CREATED
            //NODE_CHANGED
            //NODE_DELETED



        });

        curatorCache.start();
    }



}
